package it.unicam.ids.pvm.distributore;

import it.unicam.ids.pvm.data.CasellaDAO;
import it.unicam.ids.pvm.data.DAOFactory;

import java.util.ArrayList;
import java.util.Iterator;

/**
 * La classe rappresenta la spirale che eroga il prodotto, 
 * posta all'interno di una casella. Contiene i seguenti attributi:
 * casella, la casella a cui la spirale è associata.
 * @author Luca Iachini, Valerio Iachini, Alessandro Cardenà
 *
 */
public class Spirale {
	
	private ArrayList<SpiraleEventListener> _listeners = new ArrayList<SpiraleEventListener>();
	private Casella casella;
	private CasellaDAO casellaDAO;

	/**
	 * Costruttore della classe.
	 * Inizializza il valore della casella.
	 * @param casella
	 */
	
	public Spirale(Casella casella) {
		this.casella = casella;
		casellaDAO=DAOFactory.getDAOFactory().getCasellaDAO();
	}

	/**
	 * Il metodo consente di attivare la spirale, 
	 * per consentire l'erogazione del prodotto.
	 * Viene aggiornato il valore della quantità 
	 * del prodotto erogato, all'interno della tabella 
	 * relativa alla casella del prodotto, nel database.
	 * @throws Exception.
	 */
	
	public void giraSpirale() throws Exception {

		try {
			fireEventInizio();
			Thread.sleep(5000);
			if(casella.getQuantita()>=1)
			casella.setQuantita(casella.getQuantita()-1);
			casellaDAO.update(casella, casella.getEtichetta());
			fireEventStop();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	/**
	 * Il metodo consente di aggiungere un gestore di eventi 
	 * della spirale, alla lista dei gestori.
	 * @param listener gestore degli eventi da aggiungere.
	 */

	public synchronized void addEventListener(SpiraleEventListener listener) {
		_listeners.add(listener);
	}

	/**
	 * Il metodo consente di rimuovere un gestore di eventi 
	 * della spirale, dalla lista dei gestori.
	 * @param listener gestore degli eventi da eliminare.
	 */
	
	public synchronized void removeEventListener(SpiraleEventListener listener) {
		_listeners.remove(listener);
	}
	
	/**
	 * Il metodo consente di azionare l'evento di movimento 
	 * della spirale.
	 */

	private synchronized void fireEventInizio() {
		SpiraleEvent event = new SpiraleEvent(this, casella);
		Iterator<SpiraleEventListener> i = _listeners.iterator();
		while (i.hasNext()) {
			((SpiraleEventListener) i.next()).spiraleInMovimento(event);
		}
	}
	
	/**
	 * Il metodo consente di fermare un eventi di movimento 
	 * della spirale.
	 */

	private synchronized void fireEventStop() {
		SpiraleEvent event = new SpiraleEvent(this, casella);
		Iterator<SpiraleEventListener> i = _listeners.iterator();
		while (i.hasNext()) {
			((SpiraleEventListener) i.next()).spiraleFerma(event);
		}
		
	}

}
